package optimizers.randomwalk;

import java.util.HashMap;
import java.util.Random;

import optimizers.commons.GAConstants;
import optimizers.commons.GAIndiv;
import optimizers.commons.GenericGA;
import optimizers.commons.Logger;
import optimizers.commons.RunConfig;
import runconfiguration.SinConfiguration;

public class RandomGA extends GenericGA{
	
	public static int nbSimpleSequences = 2; // defaults
	public static double activationProba = 0.1; //10% chance
	Random rnd = new Random();
	
	public RandomGA(RunConfig config){
		super(config);
	}
	
	public  GAIndiv getInitialIndividual(){
		int index = 0;
		int geneLength = getGeneLength();
		double[] genes = new double[geneLength];
		if(this.config.seqK.optimizeMechanism == RunConfig.SEQK_OPTIMIZE_YES){
			for(int i = 0; i<RandomGA.nbSimpleSequences; i++){
				genes[index] = rnd.nextDouble()*(this.config.seqK.maxValue-this.config.seqK.minValue) + this.config.seqK.minValue;
				index++;
			}
		}
		if(this.config.inhK.optimizeMechanism == RunConfig.INHK_OPTIMIZE_YES){
			for(int i = 0; i<RandomGA.nbSimpleSequences*RandomGA.nbSimpleSequences; i++){
				genes[index] = rnd.nextDouble()*(this.config.inhK.maxValue-this.config.inhK.minValue) + this.config.inhK.minValue;
				index++;
			}
		}
		if(this.config.seqC.optimizeMechanism == RunConfig.SEQC_OPTIMIZE_YES){
			for(int i = 0; i<RandomGA.nbSimpleSequences; i++){
				genes[index] = rnd.nextDouble()*(this.config.seqC.maxValue-this.config.seqC.minValue) + this.config.seqC.minValue;
				index++;
			}
		}
		for(int i = 0; i<(RandomGA.nbSimpleSequences+1)*RandomGA.nbSimpleSequences*RandomGA.nbSimpleSequences;i++){
			if(rnd.nextDouble() <= RandomGA.activationProba){ //10% chance of activation
				genes[index] = this.config.template.optimizeMechanism == RunConfig.TEMPLATE_OPTIMIZE_YES?rnd.nextDouble()*(this.config.template.maxValue-this.config.template.minValue) + this.config.template.minValue : this.config.template.defaultValue;
			} else {
				genes[index] = 0;
			}
			index++;
		}
		GAIndiv initial = new GAIndiv(genes,RandomGA.nbSimpleSequences, this.config, new HashMap<String,Object>());
		initial.nametoint.put("a", 0);
		return initial;
	}

	private int getGeneLength() {
		int length = 0;
		if(this.config.seqK.optimizeMechanism == RunConfig.SEQK_OPTIMIZE_YES)
			length += RandomGA.nbSimpleSequences;
		if(this.config.inhK.optimizeMechanism == RunConfig.INHK_OPTIMIZE_YES)
			length += RandomGA.nbSimpleSequences*RandomGA.nbSimpleSequences;
		if(this.config.seqC.optimizeMechanism == RunConfig.SEQC_OPTIMIZE_YES)
			length += (RandomGA.nbSimpleSequences+1)*RandomGA.nbSimpleSequences;
		
		length += (RandomGA.nbSimpleSequences+1)*RandomGA.nbSimpleSequences*RandomGA.nbSimpleSequences; //for templates, always present
		
		//TODO: enzymes
		return length;
	}

	public GAIndiv getNewIndividual(GAIndiv parent){
		return getInitialIndividual();
	}

	public String getProblemName(){
		return "Random";
	}

	@Override
	protected void postEvaluation(GAIndiv[] nextGen) {
		// Nothing to do here
		
	}

	@Override
	protected void evolvePopulation(GAIndiv[] nextGen) {
		for(int i=0; i < nextGen.length; i++){
			GAIndiv temp = nextGen[i];
			nextGen[i] = getNewIndividual(temp);
		}
	}
	
	public static void main(String[] args){
		RunConfig config = new SinConfiguration();
		RandomGA ga = new RandomGA(config);
		RandomGA.nbSimpleSequences = 2;
		ga.run();
	}

	@Override
	protected void initAlgorithm() {
		// TODO Auto-generated method stub
		
	}
	
}
